#include "robotPlaygroundJoystick.h"
#include <jni.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/joystick.h>


JNIEXPORT jint JNICALL Java_net_zarubsys_robotplayground_joystick_JoystickNativeAccessor_openJoystick
  (JNIEnv * env, jobject obj, jstring device) {
	const char * devName = (*env)->GetStringUTFChars(env, device, NULL);
	if (devName == NULL) {
		return NULL; /* OutOfMemoryError already thrown */
	}

	int fd = open(devName, O_RDONLY);
	(*env)->ReleaseStringUTFChars(env, device, devName);
	return fd;
}

JNIEXPORT void JNICALL Java_net_zarubsys_robotplayground_joystick_JoystickNativeAccessor_closeJoystick
  (JNIEnv * env, jobject obj, jint fd) {
	close(fd);
}


JNIEXPORT jstring JNICALL Java_net_zarubsys_robotplayground_joystick_JoystickNativeAccessor_readSignature
  (JNIEnv * env, jobject obj, jint fd) {
	char joystickName[80];
	ioctl(fd, JSIOCGNAME(80), &joystickName);
	return (*env)->NewStringUTF(env, joystickName);
}


JNIEXPORT void JNICALL Java_net_zarubsys_robotplayground_joystick_JoystickNativeAccessor_readEvents
  (JNIEnv * env, jobject obj, jint fd, jobject callback) {
	printf("Accessing method!");
	jclass callbackClass = (*env)->GetObjectClass(env, callback);
	jmethodID doCloseMethod = (*env)->GetMethodID(env, callbackClass, "doClose", "()Z");
	if (doCloseMethod == NULL) {
		printf("Cannot find signature of doClose method!");
		return; /* method not found */
	}
	jmethodID callbackMethod = (*env)->GetMethodID(env, callbackClass, "callback", "(III)V");
	if (callbackMethod == NULL) {
		printf("Cannot find signature of callback method!");
		return; /* method not found */
	}

	
	

	fcntl(fd, F_SETFL, O_NONBLOCK);	/* use non-blocking mode */

	struct js_event js;
	__u32 lastEvent;
	while(1) {
		jboolean doClose = (*env)->CallBooleanMethod(env, callback, doCloseMethod);
		if (doClose) return;

		read(fd, &js, sizeof(struct js_event));
		if ((js.type == JS_EVENT_AXIS || js.type == JS_EVENT_BUTTON) && js.time != lastEvent) {
			(*env)->CallVoidMethod(env, callback, callbackMethod, js.type, js.number, js.value);
			lastEvent = js.time;
		}
		usleep(50000);
	}

}
